home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Applications / NeuroSim 1.0 / .cp / CNeuroSimPane.cp < prev    next >
Text File  |  1996-02-19  |  9KB  |  336 lines

  1. // ===========================================================================
  2. //    CNeuroSimPane.cp            ©1996 Timo Eloranta
  3. // ===========================================================================
  4. //    This class takes care of displaying the picture of the neural net.
  5. //    Derived from the PowerPlant LView class.
  6.  
  7. #include "CNeuroSimPane.h"
  8. #include "CNeuralNet.h"
  9. #include "NS_Utils.h"
  10.  
  11. #include <UDrawingState.h>
  12. #include <UGWorld.h>
  13. #include <LWindow.h>
  14.  
  15. const Uint16    kIconSize    = 16;            // Icon size in pixels
  16. const Uint16    kSquareSize = 21;            // Grid square size in pixels
  17.  
  18. const RGBColor    kBlackRGB    = { 0, 0, 0 };                    // black
  19. const RGBColor  kDarkRGB    = { 0x0A05, 0x3E90, 0x05C1 };    // dark green    
  20. const RGBColor    kBrightRGB    = { 0x1F74, 0xFFFF, 0x088A };    // bright green
  21.  
  22. // ---------------------------------------------------------------------------
  23. //        • CNeuroSimPane
  24. //
  25. //          Called by:    CNeuroSimPane::CreateNeuroSimPaneStream
  26. // ---------------------------------------------------------------------------
  27. //    Constructor. We call the base class with the LStream object reference
  28. //    and initialize some member attributes.
  29.  
  30. CNeuroSimPane::CNeuroSimPane(
  31.     LStream    *inStream )
  32.         : LView( inStream )
  33. {
  34.     Rect    theFrame;
  35.     CalcLocalFrameRect( theFrame );
  36.     mGWorld = new LGWorld( theFrame, 8 );
  37.     
  38.     if (! mGWorld )
  39.         ::StopAlert( ALRT_Offscreen, NULL );
  40.  
  41.     mNet                = NULL;
  42.     mDrawingIsDirty        = true;
  43.     mBackgroundIsDirty    = true;
  44. }
  45.  
  46. // ---------------------------------------------------------------------------
  47. //        • CreateNeuroSimPaneStream [static]
  48. //
  49. //          Called by:    CNeuroSimApp::InitNewNet (indirect call)
  50. // ---------------------------------------------------------------------------
  51. //    Return a new NeuroSimPane object initialized using data from a Stream.
  52.  
  53. CNeuroSimPane*
  54. CNeuroSimPane::CreateNeuroSimPaneStream(
  55.     LStream    *inStream)
  56. {
  57.     return ( new CNeuroSimPane( inStream ) );
  58. }
  59.  
  60. // ---------------------------------------------------------------------------
  61. //        • ~CNeuroSimPane
  62. // ---------------------------------------------------------------------------
  63. //    Destructor. Throw away the offscreen graphics world.
  64.  
  65. CNeuroSimPane::~CNeuroSimPane()
  66. {
  67.     if ( mGWorld )
  68.         delete mGWorld;
  69. }
  70.  
  71. // ---------------------------------------------------------------------------
  72. //        • SetNet
  73. //
  74. //          Called by:    CNeuroSimApp::InitNewNet
  75. // ---------------------------------------------------------------------------
  76. //    Connect the given net to this pane, init member attributes and 
  77. //    draw the net for the first time.
  78.  
  79. void
  80. CNeuroSimPane::SetNet( CNeuralNet * inNet )
  81. {
  82.     mNet         = inNet;
  83.     mGridSize    = mNet -> GetNetSize();
  84.  
  85.     // Initializiation of mGridRect
  86.  
  87.     CalcLocalFrameRect( mGridRect );
  88.     ::InsetRect( &mGridRect, 1, 1 );
  89.         
  90.     Int16    theGridWidth = mGridSize * kSquareSize;
  91.     Int16    theInset     = (mGridRect.right - theGridWidth - 2) / 2;
  92.  
  93.     ::InsetRect( &mGridRect, theInset, theInset);
  94.  
  95.     if ( theGridWidth % 2 ) {
  96.         mGridRect.right++;
  97.         mGridRect.bottom++;
  98.     }
  99.  
  100.     // Initializiation of mOneOneRect
  101.     //
  102.     // We set the "one-one" rect to the [1,1] square of the matrix.
  103.     // The size of this rect is set according to kIconSize.
  104.  
  105.     ::SetRect(     &mOneOneRect, 
  106.                 mGridRect.left    + 1,                // Left
  107.                 mGridRect.top    + 1,                // Top
  108.                 mGridRect.left    + 1 + kIconSize,    // Right
  109.                 mGridRect.top    + 1 + kIconSize);    // Bottom
  110.  
  111.     Int16    theOffset = (kSquareSize - kIconSize + 1) / 2;
  112.  
  113.     ::OffsetRect( &mOneOneRect, theOffset, theOffset);
  114.  
  115.     // Initializiation of center points
  116.     //
  117.     // Center points are used when drawing connections between neurons.
  118.     // theOneOneXY is the point in the middle of the mOneOneRect. Only 
  119.     // one value is needed, because the X and Y coordinates are equal.
  120.     
  121.     Uint16 theOneOneXY = mGridRect.left + 1 + (kSquareSize / 2);
  122.  
  123.     mNet -> SetCenterPoints( theOneOneXY, kSquareSize );
  124.     
  125.     // Finally we draw the net for the first time
  126.     
  127.     DrawTheNet();
  128. }
  129.  
  130. // ---------------------------------------------------------------------------
  131. //        • InvalidateDrawing
  132. //
  133. //          Called by:    CNeuralNet::RequestDraw
  134. // ---------------------------------------------------------------------------
  135. //    Force an immediate redraw of the net.
  136.  
  137. inline void
  138. CNeuroSimPane::InvalidateDrawing()
  139. {
  140.     mDrawingIsDirty = true;
  141.     LView::Draw( NULL );
  142. }
  143.  
  144. // ---------------------------------------------------------------------------
  145. //        • DrawSelf
  146. //
  147. //          Called by:    LView::Draw
  148. // ---------------------------------------------------------------------------
  149. //  Slam the net picture from the offscreen to the real screen...
  150.  
  151. void
  152. CNeuroSimPane::DrawSelf()
  153. {
  154.     Rect    theFrame;
  155.     
  156.     // If the net has changed and we still haven't drawn it to
  157.     // the offscreen, we better do it now...
  158.     
  159.     if ( mDrawingIsDirty ) {
  160.         DrawTheNet();
  161.         FocusDraw();
  162.     }
  163.  
  164.     CalcLocalFrameRect( theFrame );
  165.     StColorPenState::Normalize();
  166.     
  167.     if ( mGWorld )
  168.         mGWorld -> CopyImage( GetMacPort(), theFrame );
  169. }
  170.  
  171. // ---------------------------------------------------------------------------
  172. //        • ClickSelf
  173. //
  174. //          Called by:    LPane::Click
  175. // ---------------------------------------------------------------------------
  176. //    Respond to clicks in this view
  177.  
  178. void
  179. CNeuroSimPane::ClickSelf(
  180.     const SMouseDownEvent    &inMouseDown)
  181. {
  182.     Uint16        theCol, theRow;
  183.     Boolean        theOptionDown;        // Option-key held down while clicking ?
  184.  
  185.     if ( PointToSquare( inMouseDown.whereLocal, theCol, theRow ) ) {
  186.     
  187.         theOptionDown = (inMouseDown.macEvent.modifiers & optionKey) != 0;
  188.     
  189.         CNeuronPtr    theNeuron = mNet -> GetNeuron( theCol, theRow );
  190.                     theNeuron -> DoClickAction( theOptionDown );
  191.     }
  192. }
  193.  
  194. // ---------------------------------------------------------------------------
  195. //        • PointToSquare
  196. //
  197. //          Called by:    CNeuroSimPane::ClickSelf
  198. // ---------------------------------------------------------------------------
  199. //    Check if the given point is inside our net matrix.
  200. //  If not, return FALSE. If it is, return TRUE and set the values of
  201. //    outCol and outRow to point to the correct column and row.
  202.  
  203. Boolean
  204. CNeuroSimPane::PointToSquare( 
  205.     const Point    & inPoint, 
  206.     Uint16        & outCol, 
  207.     Uint16        & outRow )
  208. {
  209.     if (! ::PtInRect( inPoint, &mGridRect ) )
  210.         return false;
  211.     else {
  212.         outCol = ((inPoint.h - mGridRect.left - 1) / kSquareSize) + 1;
  213.         if ( outCol > mGridSize )
  214.             outCol = mGridSize;
  215.         
  216.         outRow = ((inPoint.v - mGridRect.top - 1) / kSquareSize) + 1;
  217.         if ( outRow > mGridSize )
  218.             outRow = mGridSize;
  219.         
  220.         return true;
  221.     }
  222. }
  223.  
  224. // ---------------------------------------------------------------------------
  225. //        • DrawTheNet
  226. //
  227. //          Called by:    CNeuroSimPane::SetNet
  228. //                        CNeuroSimPane::DrawSelf
  229. // ---------------------------------------------------------------------------
  230. //    Draw the net to our offscreen graphics world.
  231.  
  232. void
  233. CNeuroSimPane::DrawTheNet()
  234. {
  235.     if ( mGWorld ) {
  236.  
  237.         FocusDraw();
  238.         StColorPenState    theState;
  239.  
  240.         mGWorld -> BeginDrawing();                // Here we go...
  241.         
  242.         if ( mBackgroundIsDirty )
  243.             DrawBackground();
  244.             
  245.         DrawConnections    ();
  246.         DrawNeurons    ();
  247.         DrawFrame();
  248.         
  249.         mGWorld -> EndDrawing();                // Done...
  250.                                         
  251.         Rect    pRect = mGridRect;            
  252.         LocalToPortPoint( topLeft( pRect ) );
  253.         LocalToPortPoint( botRight( pRect ) );
  254.         InvalPortRect( &pRect );                // Force update
  255.         
  256.         mDrawingIsDirty = false;                // No more "dirty"...
  257.     }
  258. }
  259.  
  260. // ---------------------------------------------------------------------------
  261. //        • DrawBackground
  262. //
  263. //          Called by:    CNeuroSimPane::DrawTheNet
  264. // ---------------------------------------------------------------------------
  265. //    Draw the background black and a dark green box around the entire grid.
  266.  
  267. void
  268. CNeuroSimPane::DrawBackground()
  269. {
  270.     Rect theFrame;
  271.     
  272.     CalcLocalFrameRect( theFrame );
  273.     InsetRect( &theFrame, 1, 1);        // A nice white frame...
  274.     
  275.     ::RGBBackColor( &kBlackRGB );        // Back color is black
  276.     ::EraseRect( &theFrame);
  277.  
  278.     ::PenNormal();
  279.     ::RGBForeColor( &kDarkRGB );
  280.     ::FrameRect( &mGridRect);            // Box around the entire grid
  281.     
  282.     mBackgroundIsDirty = false;            // We only do this once!
  283. }
  284.  
  285. // ---------------------------------------------------------------------------
  286. //        • DrawConnections
  287. //
  288. //          Called by:    CNeuroSimPane::DrawTheNet
  289. // ---------------------------------------------------------------------------
  290. //    Set the color to dark green and request the net to get all connections
  291. //    between neurons to be drawn...
  292.  
  293. void
  294. CNeuroSimPane::DrawConnections()
  295. {
  296.     ::RGBForeColor( &kDarkRGB );
  297.     
  298.     mNet -> DrawConnections();
  299. }
  300.  
  301. // ---------------------------------------------------------------------------
  302. //        • DrawNeurons
  303. //
  304. //          Called by:    CNeuroSimPane::DrawTheNet
  305. // ---------------------------------------------------------------------------
  306. //    Request the net to draw its neurons.
  307.  
  308. void
  309. CNeuroSimPane::DrawNeurons()
  310. {
  311.     mNet -> DrawNeurons( mOneOneRect, kSquareSize );
  312. }
  313.  
  314. // ---------------------------------------------------------------------------
  315. //        • DrawFrame
  316. //
  317. //          Called by:    CNeuroSimPane::DrawTheNet
  318. // ---------------------------------------------------------------------------
  319. //    Draw a bright frame around the matrix.
  320.  
  321. void
  322. CNeuroSimPane::DrawFrame()
  323. {
  324.     Rect theInnerFrame = mGridRect;
  325.  
  326.     ::InsetRect( &theInnerFrame, 1, 1 );    
  327.     ::RGBForeColor( &kBrightRGB );
  328.     ::FrameRect( &theInnerFrame);
  329.  
  330.     // Draw another bright box around the receptors (left side neurons)
  331.  
  332.     theInnerFrame.right    = theInnerFrame.left + kSquareSize;
  333.     
  334.     ::FrameRect( &theInnerFrame);
  335. }
  336.